package com.easpeed.user.utils

/**
 * Created by bigyu on 2024/10/31 13:49
 * com.easpeed.user.utils
 */
import android.util.Log;
import com.bigyu.utils.Logger
import com.easpeed.comon.bean.UserOnlineStatus
import com.easpeed.comon.consts.ConstsApi
import com.easpeed.comon.memorycache.CommonMemoryCache
import com.easpeed.comon.utils.CacheHelper
import com.easpeed.comon.utils.PackageLength.dataLength
import com.easpeed.comon.utils.bytesToHex
import com.easpeed.comon.utils.SendCommand
import com.easpeed.comon.utils.SendCommand.commandUserNameOperate
import com.easpeed.user.bean.TcpBean
import com.easpeed.comon.utils.TcpData
import com.easpeed.comon.utils.compressData
import com.easpeed.user.bean.UserTcpBean
import com.easpeed.comon.utils.connectFailed
import com.easpeed.comon.utils.connectSuccess
import com.easpeed.comon.utils.decompressData
import com.easpeed.comon.utils.hexStringToJson
import com.easpeed.comon.utils.indexOfSequence
import com.easpeed.comon.utils.isUser
import com.easpeed.comon.utils.parseSinglePacket
import com.easpeed.comon.utils.print
import com.easpeed.comon.utils.receiveSuccess
import com.easpeed.comon.utils.reconnect
import com.easpeed.elevator.BuildConfig
import org.greenrobot.eventbus.EventBus
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.io.OutputStream
import java.net.Socket
import java.util.Timer
import java.util.TimerTask
import java.util.concurrent.Executors

/**
 * 0190代表有异常
 * 异常信息根据数据进行处理
 * 01为设备离线
 * 02为其他用户连接，无法简历连接
 */
class TcpClient(
    private val host: String,
    private val port: Int,
    private val deviceId: String,
    private val appType: Byte = 0x02,
    private val result: (TcpData) -> Unit,
) {
    private var socket: Socket? = null
    private var outputStream: OutputStream? = null
    private val lock = Any() // 定义锁对象
    private var inputStream: InputStream? = null

    lateinit var heartBean: UserTcpBean
    private var heartCommandPackage: ByteArray? = null
    private var userOnlineCommandPackage: ByteArray? = null
    val defaultExecutor = Executors.newSingleThreadExecutor()  // 创建一个固定大小的线程池
    val userNameExecutor = Executors.newSingleThreadExecutor()  // 创建一个固定大小的线程池
    val sendDataExecutor = Executors.newSingleThreadExecutor()  // 创建一个固定大小的线程池

    init {
        val userId = CacheHelper.instance().getStringValue("userId", "")
        heartBean = UserTcpBean(deviceId = deviceId, command = SendCommand.heartbeatCommand.bytesToHex(), data = "${ConstsApi.socketData};$userId", appType = byteArrayOf(appType).bytesToHex())
        heartCommandPackage = heartBean.createTcpPacket()
    }

    @Volatile
    private var running = true

    // 创建 TCP 连接
    private fun connect() {
        if (isConnected()) {
            Logger.e("TAG", "当前是连接状态，不需要重新连接")
            result.invoke(TcpData().connectFailed("当前是连接状态，不需要重新连接"))
            return
        }
        defaultExecutor.submit {
            try {
                Logger.e("TAG", "去连接服务器1")
                socket = Socket(host, port)
//                socket?.setSendBufferSize(1024 * 1024) // 设置发送缓冲区为1MB
//                socket?.setReceiveBufferSize(1024 * 1024) // 设置接收缓冲区为1MB
                // 设置 TCP_NODELAY 选项
//                socket?.tcpNoDelay = true
                outputStream = socket?.getOutputStream()
                inputStream = socket?.getInputStream()
                Logger.e("TAG", "去连接服务器2")
                result.invoke(TcpData().connectSuccess("连接成功"))
                Logger.e("TAG", "socket 连接成功")
                sendHeartbeat()
                sendUserName()
                readResponse() // 启动读取响应的线程
            } catch (e: Exception) {
                e.printStackTrace()
                defaultExecutor.shutdownNow()
                result.invoke(TcpData().reconnect(""))
                Logger.e("TAG", "连接服务器失败: ${e.message}")
            }
        }
    }


    fun isConnected(): Boolean {
        return socket?.isConnected == true
    }

    // 断开连接
    private fun disconnect() {
        try {
            if (!isUser()) {
                EventBus.getDefault().post(UserOnlineStatus(false))
            }

            running = false
            timer?.cancel()
            timer = null
            inputStream?.close()
            inputStream = null
            outputStream?.close()
            outputStream = null
            socket?.close()
            socket = null
            result.invoke(TcpData().connectFailed("断开连接"))
            Logger.e("TAG", "跟服务端断开连接")

        } catch (e: Exception) {
            Logger.e("TAG", "Error disconnecting: ${e.message}")
        }
    }

    private var timer: Timer? = null

    // 发送心跳包
    private fun sendHeartbeat() {
        if (!isConnected()) {
            return
        }
        timer = Timer()
        timer?.schedule(object : TimerTask() {
            override fun run() {
                try {
                    "************发送心跳包************".print()
                    heartCommandPackage?.let {
//                        if (BuildConfig.DEBUG) {
//                            Logger.e("TAG", "实际报文=> ${it.joinToString(" ") { String.format("%02X", it) }}", )
//                            parseSinglePacket(it)
//                        }
                        writeData(it)
                    }
                } catch (e: Exception) {
//                    disconnect()
                    Logger.e("TAG", "发送心跳失败: ${e.message}")
                    result.invoke(TcpData().reconnect(""))
//                    reConnect()
                }
            }
        }, 0, 10000) // 每 10 秒发送一次心跳
    }


    fun sendUserName() {
        if (!isConnected()) {
            return
        }
        if (!isUser()) {
            return
        }
        userNameExecutor.submit {
            val msg = UserTcpBean(deviceId = deviceId, command = SendCommand.commandUserNameOperate.bytesToHex(), data = "${CommonMemoryCache.deviceName}", appType = byteArrayOf(appType).bytesToHex())
            "************发送用户名************".print()
            val createTcpPacket = msg.createTcpPacket(true)
            parseSinglePacket(createTcpPacket, true)
            writeData(createTcpPacket)
        }
    }

    private fun writeData(data: ByteArray) {
        outputStream?.write(data)
        outputStream?.flush()
    }

    fun sendData(data: ByteArray) {
        if (!isConnected()) {
            Logger.e("TAG", "sendData: 服务器未连接 ")
            return
        }
        sendDataExecutor.submit {
            try {
                writeData(data)
//                try {
//                    TcpBean().parseData(data)
//                } catch (e: Exception) {
//                    e.printStackTrace()
//                }
                if (BuildConfig.DEBUG) {
//                    parseSinglePacket(data)
                }
                if (ConstsApi.isShowSocketLog) {
                    Logger.e("TAG", "数据包发送完成↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑")
                    Logger.e("TAG", "")
                    Logger.e("TAG", "")
                }

            } catch (e: Exception) {
                Logger.e("TAG", "发送数据包失败: ${e.message}")
            }
        }
    }

    // 假设 TcpBean 和 TcpData 是你的数据类
// TcpBean: 用于封装解析后的数据
// TcpData: 用于进一步处理和传递解析后的数据


    /**
     * TCP通信协议
     * 帧头  3字节
     * 设备ID号  8字节
     * APP类型   1：设备端   2：用户端    1字节
     * 命令   2字节
     * 数据长度    2字节
     * 数据     数据长度字节
     * 结束帧    3字节
     */
    private fun readResponse() {
        val buffer = ByteArray(1024 * 1024 * 5)  // 假设最大响应大小
        val tempBuffer = ByteArrayOutputStream()  // 用于存储接收到的数据
        while (running) {
            try {
                // 从 inputStream 读取数据
                val bytesRead = inputStream?.read(buffer) ?: -1
                if (!running) {
                    break
                }
                if (bytesRead > 0) {
                    "收到服务端数据包===>数据长度: $bytesRead".print()

                    // 将接收到的数据写入临时缓冲区
                    tempBuffer.write(buffer, 0, bytesRead)
                    // 将累积的数据转换为字节数组
                    var tempBytes = tempBuffer.toByteArray()
                    // 解析数据
                    while (tempBytes.isNotEmpty()) {
                        if (!running) {
                            break
                        }
                        tempBuffer.reset()
                        "".print()
                        "循环处理数据包===>数据长度: ${tempBytes.size}".print()
                        val packet = parseSinglePacket(tempBytes)
//                        tempBytes.bytesToHex().print()
                        "解析成功 ${packet != null}  处理长度：${packet?.dataLength ?: -1}  原始数据 ${tempBytes.size}".print()

                        if (packet != null) {
                            // 处理解析后的数据包
                            result.invoke(TcpData().receiveSuccess(packet))
                            // 计算完整包的长度（帧头 + 数据 + 结束帧）
                            val packetLength = 21 + packet.dataLength  // 包头 + 数据长度 + 结束帧
                            // 更新 tempBytes，移除已解析的部分
                            // 如果包头不是第一个字节，需要先找到帧头的位置
                            val headerIndex = tempBytes.indexOfSequence(byteArrayOf(0x7F, 0x7E, 0x7F))
                            if (headerIndex != -1) {
                                // 如果帧头存在，从帧头开始截取
                                tempBytes = tempBytes.copyOfRange(headerIndex + packetLength, tempBytes.size)
                            }
                            tempBuffer.write(tempBytes, 0, tempBytes.size)
                        } else {
                            // 如果没有完整的包，跳过错误部分，并继续处理剩余的字节
                            val headerIndex = tempBytes.indexOfSequence(byteArrayOf(0x7F, 0x7E, 0x7F))
                            if (headerIndex != -1) {
                                // 只跳过当前无效部分，保留接下来的数据继续处理
                                tempBytes = tempBytes.copyOfRange(headerIndex, tempBytes.size)
                                tempBuffer.write(tempBytes, 0, tempBytes.size)
                                break
                            } else {
                                // 如果找不到帧头，丢弃整个数据部分
                                tempBytes = byteArrayOf() // 清空当前的 tempBytes，丢弃无法解析的数据
                            }
                        }
                        if (tempBytes.isEmpty()) {
                            tempBuffer.reset() // 清空缓冲区
                            "数据包处理完成,等等下个数据包===>数据长度: ${tempBytes.size}".print()
                            break
                        }

                    }
                }
            } catch (e: Exception) {
                Logger.e("TAG", "Error reading response: ${e.message}")
            }
        }
    }


    private fun readResponse11111111() {
        Thread {
            val buffer = ByteArray(1024 * 1024 * 4) // 假设最大响应大小
            val tempBuffer = ByteArrayOutputStream() // 使用 ByteArrayOutputStream 累积接收数据

            while (running) {
                try {
                    val bytesRead = inputStream?.read(buffer) ?: -1
                    if (bytesRead > 0) {
                        // 将接收的数据追加到 ByteArrayOutputStream
                        tempBuffer.write(buffer, 0, bytesRead)

                        // 转换为 byteArray 进行数据解析
                        val tempBytes = tempBuffer.toByteArray()

                        while (tempBytes.size >= 19) { // 最小包长度为19字节
                            // 查找帧头
                            val headerIndex = tempBytes.indexOfSequence(byteArrayOf(0x7F, 0x7E, 0x7F))
                            if (headerIndex == -1) break

                            if (tempBytes.size < headerIndex + 19) break

                            // 提取协议固定字段
                            val deviceId = tempBytes.copyOfRange(headerIndex + 3, headerIndex + 11).toString(Charsets.US_ASCII)
                            val appType = tempBytes[headerIndex + 11].toInt()
//                            val command2 = tempBytes.sliceArray(12..13)
                            val command2 = tempBytes.copyOfRange(headerIndex + 12, headerIndex + 14) // 修改为相对位置

                            val dataLength = ((tempBytes[headerIndex + 14].toInt() and 0xFF) shl 8) or (tempBytes[headerIndex + 15].toInt() and 0xFF)

                            //headerIndex + 19 + dataLength完整的包长度
                            if (tempBytes.size < headerIndex + 19 + dataLength) break// 等待数据完整

                            val data = tempBytes.copyOfRange(headerIndex + 16, headerIndex + 16 + dataLength)

                            // 检查结束帧
                            val endFrame = tempBytes.copyOfRange(headerIndex + 16 + dataLength, headerIndex + 19 + dataLength)
                            if (!endFrame.contentEquals(byteArrayOf(0x6F, 0x6E, 0x6F))) {
                                // 帧结束符不匹配，跳过帧头及错误部分
                                tempBuffer.reset()
                                // 跳过错误的帧头,这里并不会影响数据不完整的情况，因为在上面已经判断了break条件
                                tempBuffer.write(tempBytes, headerIndex + 3, tempBytes.size - (headerIndex + 3))
                                continue
                            }

                            // 处理数据
                            val transData = String(data, Charsets.UTF_8)
                            result.invoke(TcpData().receiveSuccess(TcpBean().apply {
                                this.deviceId = deviceId
                                this.appType = String.format("%02X", appType)
                                this.command = command2.bytesToHex()
                                this.dataLength = dataLength
                                this.originalData = data.bytesToHex()
                                this.data = transData
                            }))
                            if (BuildConfig.DEBUG) {
                                if (ConstsApi.isShowSocketLog) {
                                    Logger.e("TAG", "解析数据包成功=============================")
                                    Logger.e("TAG", "设备ID号: $deviceId")
                                    Logger.e("TAG", "APP类型: ${String.format("%02X", appType)}")
                                    Logger.e("TAG", "命令：  ${command2.bytesToHex()}")
                                    Logger.e("TAG", "数据长度 ${dataLength}")
                                    Logger.e("TAG", "转换后的数据 ${transData}")
                                    Logger.e("TAG", "数据 ${data.bytesToHex()}")
                                }

                            }
                            // 移除已处理的数据包
                            tempBuffer.reset()
                            tempBuffer.write(tempBytes, headerIndex + 19 + dataLength, tempBytes.size - (headerIndex + 19 + dataLength))
                        }
                    }
                } catch (e: Exception) {
                    Logger.e("TAG", "Error reading response: ${e.message}")
                }
            }
        }.start()
    }

    private fun readResponse1111() {
        Thread {
            val buffer = ByteArray(1024 * 1024 * 4) // 假设最大响应大小
            var tempBuffer = ByteArray(0) // 临时缓冲区用于累积接收到的数据

            while (running) {
                try {
                    val bytesRead = inputStream?.read(buffer) ?: -1
                    if (bytesRead > 0) {
                        // 将接收的数据累加到临时缓冲区
                        tempBuffer += buffer.copyOfRange(0, bytesRead)

                        // 尝试解析完整数据包
                        while (tempBuffer.size >= 19) { // 最小包长度为19字节
                            // 查找帧头
                            val headerIndex = tempBuffer.indexOfSequence(byteArrayOf(0x7F, 0x7E, 0x7F))
                            if (headerIndex == -1) break

                            // 确保帧头之后至少有16字节数据（8字节ID + 1字节APP类型 + 2字节命令 + 2字节数据长度 + 3字节结束帧）
                            if (tempBuffer.size < headerIndex + 19) break

                            // 提取协议固定字段
                            val deviceId = tempBuffer.copyOfRange(headerIndex + 3, headerIndex + 11).toString(Charsets.US_ASCII)
                            val appType = tempBuffer[headerIndex + 11].toInt()
//                            val command = ((tempBuffer[headerIndex + 12].toInt() and 0xFF) shl 8) or (tempBuffer[headerIndex + 13].toInt() and 0xFF)
                            val command2 = tempBuffer.sliceArray(12..13)
                            val dataLength = ((tempBuffer[headerIndex + 14].toInt() and 0xFF) shl 8) or (tempBuffer[headerIndex + 15].toInt() and 0xFF)

                            // 确保接收完整的数据包
                            if (tempBuffer.size < headerIndex + 19 + dataLength) break

                            // 提取数据
                            val data = tempBuffer.copyOfRange(headerIndex + 16, headerIndex + 16 + dataLength)

                            // 检查结束帧
                            val endFrame = tempBuffer.copyOfRange(headerIndex + 16 + dataLength, headerIndex + 19 + dataLength)
                            if (!endFrame.contentEquals(byteArrayOf(0x6F, 0x6E, 0x6F))) {
                                // 结束帧不匹配，忽略错误的帧
                                tempBuffer = tempBuffer.copyOfRange(headerIndex + 3, tempBuffer.size)
                                continue
                            }

                            // 移除已处理的数据包
                            tempBuffer = tempBuffer.copyOfRange(headerIndex + 19 + dataLength, tempBuffer.size)


                            Logger.e("TAG", "获取到数据包")

                            val startTime = System.currentTimeMillis()

                            val transData = String(data, Charsets.UTF_8)

                            val transDataTime = System.currentTimeMillis()
                            // 处理数据包
                            result.invoke(TcpData().receiveSuccess(TcpBean().apply {
                                this.deviceId = deviceId
                                this.appType = String.format("%02X", appType)
                                this.command = command2.bytesToHex()
                                this.dataLength = dataLength
                                this.originalData = data.bytesToHex()
                                this.data = transData
                            }))
                            Logger.e("TAG", "所有数据包解析时间 ${System.currentTimeMillis() - startTime} 数据转UTF-8时间 ${transDataTime - startTime} ")

                            if (BuildConfig.DEBUG) {
                                Logger.e("TAG", "设备ID号: $deviceId")
                                Logger.e("TAG", "APP类型: ${String.format("%02X", appType)}")
                                Logger.e("TAG", "命令  ${command2.bytesToHex()}")
                                Logger.e("TAG", "数据长度 ${dataLength}")
                                Logger.e("TAG", "转换后的数据 ${transData}")
                                Logger.e("TAG", "数据 ${data.bytesToHex()}")
                            }
                        }
                    }
                } catch (e: Exception) {
                    Logger.e("TAG", "Error reading response: ${e.message}")
                }
            }
        }.start()
    }


    // 启动心跳线程
    fun startHeartbeat() {
        connect() // 连接服务器
    }

    // 停止心跳线程
    fun stopHeartbeat() {
        disconnect()
    }


}

